<?php

namespace app\wxapp\service;

use app\common\model\WechatUser;
use app\common\service\UserService;
use app\common\util\CacheKey;
use EasyWeChat\Factory;
use Firebase\JWT\JWT;
use app\wxapp\model\WechatUser as WechatUserModel;
use think\facade\Cache;
use think\facade\Db;
use EasyWeChat\Kernel\Messages\Text;

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/9/29 0029
 * Time: 9:38
 */
class WechatUserService
{

    public function login($code)
    {
        $appid = env("wxapp.appid");
        $secret = env("wxapp.secret");

        if (empty($appid) || empty($secret)) {
            throw new \Exception('登录失败');
        }

        $get_token_url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $appid . '&secret=' . $secret . '&js_code=' . $code . '&grant_type=authorization_code';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $get_token_url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);

        //不知道为什么去掉这个在之前的项目中运行的好好的 这里就不行
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // 对认证证书来源的检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 从证书中检查SSL加密算法是否存在

        $res = curl_exec($ch);
        curl_close($ch);
        $res = json_decode($res, true);

        $openid = '';
        if ($res && !empty($res['openid'])) {
            $openid = $res['openid'];
            $sessionKey = $res['session_key'];
            Cache::set(CacheKey::WXAPP . "#" . $openid . "#session_key", $sessionKey);
        }

        if (empty($openid)) {
            throw new \Exception('登录失败');
        }

        //处理用户数据
        $condition = ['openid' => $openid];
        $user = WechatUserModel::where($condition)->find();
        if (!$user) {
            $user = WechatUserModel::create([
                'openid' => $openid
            ]);
        }
        // 更新用户登录时间
        $user->login_time = date('Y-m-d H:i:s');
        $user->save();

        $expire = 3600 * 2;
        $time = time();
        $payload = array(
            'exp' => $time + $expire,
            "id" => $user->id,
            't' => 'wxapp' //类型为 总后台登录
        );
        $jwtKey = env('jwt.key');
        $token = JWT::encode($payload, $jwtKey);
        $refreshPayload = [
            'exp' => $time + 3600 * 24 * 7,
            'id' => $user->id,
            't' => 'wxapp'
        ];
        $refreshToken = JWT::encode($refreshPayload, $jwtKey);

        $this->clearUserCache($user->id);

        return ['token' => $token, 'refresh_token' => $refreshToken];
    }

    private function clearUserCache($userId)
    {
        //清空上次登录缓存，及时更新登录信息 clear 会清楚调全部缓存
        Cache::delete(CacheKey::WXAPP . "#" . $userId);
    }

    /**
     * 获取用户的偏好设置
     * @param $userId
     * @return mixed
     */
    public function getSelectedCategory($userId)
    {
        $res = Cache::get(CacheKey::WXAPP . "#category_selected#" . $userId);
        if (empty($res)) {
            $res = Db::table("wechat_user")->where(['id' => $userId])->column('category_selected');
            try {
                $res = json_decode($res[0]);
            } catch (\Exception $e) {
                $res = [];
            }
            if (empty($res)) {
                $res = Db::table("category")->column("id");
            }
        }
        return $res;
    }

    public function saveSelectedCategory($data, $user)
    {
        $keys = [];
        foreach ($data as $key => $val) {
            if ($val) {
                array_push($keys, $key);
            }
        }
        $json = json_encode($keys);
        Db::table("wechat_user")->where(['id' => $user['id']])->update(['category_selected' => $json]);
        Cache::set(CacheKey::WXAPP . "#category_selected#" . $user['id'], $keys);
    }


    /**
     * 更新用户信息
     * @param $data
     * @param $userId
     * @return mixed
     */
    public function update($data, $userId)
    {
        $updateData = [];
        $updateData['nick_name'] = empty($data['nickName']) ? '' : $data['nickName'];
        $updateData['gender'] = empty($data['gender']) ? '' : $data['gender'];
        $updateData['language'] = empty($data['language']) ? '' : $data['language'];
        $updateData['country'] = empty($data['country']) ? '' : $data['country'];
        $updateData['province'] = empty($data['province']) ? '' : $data['province'];
        $updateData['city'] = empty($data['city']) ? '' : $data['city'];
        $updateData['avatar_url'] = empty($data['avatarUrl']) ? '' : $data['avatarUrl'];
        WechatUser::update($updateData, ['id' => $userId]);
        return WechatUser::find($userId);
    }


    public function updatePhone($post, $userId)
    {
        $user = WechatUser::find($userId);
        $openid = $user['openid'];
        $sessionKey = Cache::get(CacheKey::WXAPP . "#" . $openid . "#session_key");
        $iv = $post['iv'];
        $encrypt = $post['encryptedData'];

        $aesKey = base64_decode($sessionKey);
        $aesIV = base64_decode($iv);
        $aesCipher = base64_decode($encrypt);
        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
        $dataObj = json_decode($result, true);

        if (!empty($dataObj['phoneNumber'])) {
            $data = [];
            $data['mobile'] = $dataObj['phoneNumber'];
            WechatUser::update($data, ['id' => $userId]);
            $user['mobile'] = $data['mobile'];
        }
        return $user;
    }

    /**
     * 变更课程提醒状态
     * @param $userId
     * @param $status
     * @param $time
     * @return bool|null
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function remindStudy($userId, $status, $time)
    {
        $status = (int)$status;
        if (!in_array($status, [0, 1, 2])) {
            return null;
        }
        if (2 === $status && !preg_match('/^\d{2}:\d{2}$/', $time)) {
            return null;
        }

        // 更新状态
        if ($remind = Db::table('user_remind')->where('uid', $userId)->find()) {
            Db::table('user_remind')->where('uid', $userId)->update([
                'status' => $status,
                'time' => $time
            ]);
        } else {
            Db::table('user_remind')->insert([
                'status' => $status,
                'uid' => $userId,
                'time' => $time
            ]);
        }
        return true;
    }

    /**
     * 获取课程提醒状态
     * @param $userId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function remindStatus($userId)
    {
        if ($remind = Db::table('user_remind')->where('uid', $userId)->find()) {
            return ['status' => $remind['status'], 'time' => $remind['time']];
        } else {
            return ['status' => 0, 'time' => '00:00'];
        }
    }
}